/*
 * CorsoBridge.java
 *
 * Created on 06. Juni 2007, 07:42
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package sbc;

import org.xvsm.api.core.*;
import org.xvsm.client.ClientCapi;
import org.xvsm.api.core.notification.*;
import java.util.*;
import sbc.corso.util.*;
import sbc.factory.SensorFeature;
import sbc.corso.*;
import sbc.fact.*;
import sbc.factory.*;
import sbc.util.*;
import corso.lang.*;
import org.apache.log4j.*;
import sbc.util.Bridge;
import sbc.util.BridgeException;


/**
 *
 * @author mustermark
 */
public class CorsoBridge extends CorsoConnectionHolder implements Bridge<List<Entry>>, Runnable {
    
    private Capi capi;
    static Logger logger = Logger.getLogger(CorsoBridge.class);
    private List<CorsoVarOid> clientOids = new ArrayList<CorsoVarOid>();
    
    public CorsoBridge(Capi c) {
        super();
        capi = c;
        establish();
        
    }
    
    public void disestablish() {
        
    }
    public void establish() {
        try {
            CorsoVarOid uninspectedSensorChannelOid = con.getOrCreateNamedVarOid(con.getCurrentStrategy(), "uninspectedSensors", null);
            CorsoVarOid inspectedSensorChannelOid = con.getOrCreateNamedVarOid(con.getCurrentStrategy(), "inspectedSensors", null);
            CorsoVarOid unitChannelOid = con.getOrCreateNamedVarOid(con.getCurrentStrategy(), "units", null);
            CorsoVarOid readyUnitChannelOid = con.getOrCreateNamedVarOid(con.getCurrentStrategy(), "readyUnits", null);
            CorsoConstOid boardPipeOid = con.getOrCreateNamedConstOid(con.getCurrentStrategy(), "boards", null);
            
        } catch(Exception e) {
            System.out.println("Couldn' create Channels - FATAL");
            e.printStackTrace();
            System.exit((-13));
        }
                
        Thread t = new Thread(this);
        t.start();
    }
       
    public void route(List<Entry> entries) throws BridgeException {
        for(Entry en : entries) {
            if(en.getType() == ValueTypes.TUPLE) {
                route((Tuple)en);

            }

        }
    }
    private void route(Tuple t) throws BridgeException {
        List<Entry> vals = t.getValue();
        String modType = ((String)vals.get(0).getValue()).toUpperCase();
        String[] featStrings = null;
        String id = (String)vals.get(1).getValue();
        System.out.println("type: " + modType);
        System.out.println("ID: " + id);
        if(modType.equals(ModuleType.SENSOR.toString())) {
            featStrings = new String[vals.size() - 2];
            for(int i = 2; i < vals.size(); i++) {
                
                featStrings[i-2] = ((String)vals.get(i).getValue()).toUpperCase();
                System.out.println("ID: " + featStrings[i-2]);
            }
        }
        
        if(featStrings != null) {
            EnumSet<SensorFeature> features = EnumSet.noneOf(SensorFeature.class);
            for(int i = 0; i < featStrings.length; i++) features.add(SensorFeature.valueOf(featStrings[i]));
            try {
                CorsoVarOid channelOid = new CorsoVarOid();
                channelOid = con.getNamedVarOid("uninspectedSensors", site, null, false, CorsoConnection.NO_TIMEOUT);
                
                // create object ******************************************************
                SensorChannel uninspectedSensorChannel = new SensorChannel(channelOid);

                Sensor s = new Sensor(id, features);
                SensorLinker linker = new SensorLinker();
                linker.sensor = s;
                linker.next = con.createConstOid (con.getCurrentStrategy());
                uninspectedSensorChannel.appendModuleLinker(linker);
                System.out.println("appended " + s + " to sensorChannel");
            } catch(Exception e) {
                System.out.println("Couldn't write to Channel -  should remove it from bridge...");
                e.printStackTrace();
                
            }
        } else {
            try {
                CorsoConstOid boardPipeOid = con.getNamedConstOid("boards", site, null, false, CorsoConnection.NO_TIMEOUT);
                CorsoPipe boardPipe = new CorsoPipe(boardPipeOid);
        
                CorsoVarOid moduleOid = con.createNamedVarOid(con.getCurrentStrategy(), id, null);
                Module mod = new Board(id);
                
                boardPipe.append(mod);
                System.out.println("appended " + id + " to baordchannel");
            } catch(Exception e) {
                System.out.println("Couldn't write to Channel -  should remove it from bridge...");
                e.printStackTrace();
            }
        }
        
    }

    public void run() {

        try {
            final ContainerRef cref = Util.getOrCreateNamedContainer(capi, sbc.xvsm.Defaults.CONTAINER.toString(), CoordinationTypes.FIFO);
            capi.createNotification(cref, -1, NotificationTarget.WRITE.code(), NotificationMode.INFINITE, true, new NotificationListener() {
                public void sendNotification(NotificationID id) {
                    System.out.println("sending " + id);
                    try { 
                        route(capi.take(cref)); 
                    } catch(Exception ex) { 
                        System.out.println("Couldn't route...");
                    }

                }

                public void sendNotification(NotificationID id, java.util.List<Entry> entries) {
                    System.out.println("sending " + id + " with " + entries);
                    //route(entries);
                    try { 
                        route(capi.take(cref)); 
                    } catch(Exception ex) { 
                        System.out.println("Couldn't route " + entries);
                        System.out.println(ex);
                    }
                }


            });
        } catch(Exception ex) { ex.printStackTrace(); }

    }

   // }
    
    public static void main(String[] args) {
        Capi capi;
        if (args.length != 1) {
            System.out.println("URL needed!");
            System.out.println("Usage: java -cp <classpath> org.xvsm.example.Fifo http://localhost:8084/xvsm/xvsm\n using embeded core");
            // use embeded xvsm core
            capi = CapiFactory.createCapi();
            //capi = new ClientCapi("http://localhost:8084/xvsm-0.8.3");
        } else {
        // Get an instance of the capi and initialize it.
        // Capi capi = CapiFactory.createCapi();
          capi = new ClientCapi(args[0]);
        }
        //capi.init(false);
        CorsoBridge bridge = new CorsoBridge(capi);
        //bridge.addClient(Factory.DEFAULT_FACTORY_NAME);
        //bridge.establish();
        
        //UI ui = new UI("http://localhost:8084/xvsm-0.8.3");
    }
    
}
